package edu.uoc.tds.pec4.vista;

import edu.uoc.tds.pec4.model.SS1_TipoEvento;
import edu.uoc.tds.pec4.model.SS2_Evento;
import edu.uoc.tds.pec4.model.SS4_Acceso;
import edu.uoc.tds.pec4.model.SS4_DatosInscripcion;
import edu.uoc.tds.pec4.util.ExceptionUtils;
import edu.uoc.tds.pec4.util.KeyValue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.rmi.RemoteException;
import javax.swing.JLabel;
import javax.swing.JPanel;
import edu.uoc.tds.pec4.util.LanguageUtils;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import edu.uoc.tds.pec4.vista.base.JPanelBase;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Date;
import javax.swing.table.DefaultTableModel;

/**
 * Tecnicas de Desarrollo de Software - (UOC)
 * Clase para visualizar la pantalla de inscripcion de un evento
 * @author Pedro Bauzá Picó
 * @version 1.0
 */
public class SS4_PantallaInscripcion extends JPanelBase {

    final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    private SS4_PantallaMenu SS4_PantallaMenu;
    private JLabel jlabel_TipoEvento;
    private JComboBox jcomboBox_TipoEvento;
    private JLabel jlabel_FechaInicial;
    private JTextField jtextfield_FechaInicial;
    private JLabel jlabel_FechaFinal;
    private JTextField jtextfield_FechaFinal;
    private JButton jbutton_Buscar;
    private JButton jbutton_Inscribirse;
    private JLabel jlabel_Informacion;
    private JTable tableInformacion;
    private JScrollPane scrollPanelInformacion;
    private JTextArea jtextarea_Descripcion;
    private JPanel panelCentral;
    private JButton jbutton_Salir;
    private SS4_Acceso acceso;
    private SS4_DatosInscripcion datosInscripcion;

    public SS4_PantallaInscripcion(SS4_PantallaMenu SS4_PantallaMenu) {
        super();
        this.SS4_PantallaMenu = SS4_PantallaMenu;
        this.acceso = SS4_PantallaMenu.getAcceso();
        iniciarComponentes();
    }

    /*
     * Método para iniciar los componentes que contiene la pantalla
     */
    private void iniciarComponentes() {
        jlabel_TipoEvento = new JLabel(LanguageUtils.getMessage("InscripcionEvento.jlabel_TipoEvento.titulo"));
        jlabel_TipoEvento.setBounds(new Rectangle(20, 20, 176, 25));
        jcomboBox_TipoEvento = new JComboBox();
        jcomboBox_TipoEvento.setSelectedItem(jcomboBox_TipoEvento);
        jcomboBox_TipoEvento.setToolTipText(LanguageUtils.getMessage("InscripcionEvento.jcomboBox_TipoEvento.ToolTipText"));
        jcomboBox_TipoEvento.setBounds(new Rectangle(20, 60, 160, 25));
        setListTipoEventoToCombo(jcomboBox_TipoEvento);
        jlabel_FechaInicial = new JLabel(LanguageUtils.getMessage("InscripcionEvento.jlabel_FechaInicial.titulo"));
        jlabel_FechaInicial.setBounds(new Rectangle(20, 220, 176, 25));
        jtextfield_FechaInicial = new JTextField();
        jtextfield_FechaInicial.setBounds(new Rectangle(100, 220, 80, 25));
        jlabel_FechaFinal = new JLabel(LanguageUtils.getMessage("InscripcionEvento.jlabel_FechaFinal.titulo"));
        jlabel_FechaFinal.setBounds(new Rectangle(20, 260, 176, 25));
        jtextfield_FechaFinal = new JTextField();
        jtextfield_FechaFinal.setBounds(new Rectangle(100, 260, 80, 25));
        jbutton_Buscar = new JButton();
        jbutton_Buscar.setText(LanguageUtils.getMessage("InscripcionEvento.jbutton_Buscar.titulo"));
        jbutton_Buscar.setName("jbutton_Aceptar");
        jbutton_Buscar.setBounds(new Rectangle(20, 315, 160, 25));
        jbutton_Inscribirse = new JButton();
        jbutton_Inscribirse.setText(LanguageUtils.getMessage("InscripcionEvento.jbutton_Inscribirse.titulo"));
        jbutton_Inscribirse.setName("jbutton_Inscribirse");
        jbutton_Inscribirse.setBounds(new Rectangle(20, 355, 160, 25));
        jbutton_Salir = new JButton();
        jbutton_Salir.setText(LanguageUtils.getMessage("InscripcionEvento.jbutton_Salir.titulo"));
        jbutton_Salir.setName("jbutton_Salir");
        jbutton_Salir.setBounds(new Rectangle(20, 395, 160, 25));
        jlabel_Informacion = new JLabel(LanguageUtils.getMessage("InscripcionEvento.jlabel_Informacion.titulo"));
        jlabel_Informacion.setBounds(new Rectangle(210, 20, 176, 25));
        scrollPanelInformacion = new JScrollPane(montarTablaInformacion());
        scrollPanelInformacion.setBounds(new Rectangle(210, 60, 465, 140));
        jtextarea_Descripcion = new JTextArea(5, 20);
        jtextarea_Descripcion.setBounds(new Rectangle(210, 220, 465, 205));
        jtextarea_Descripcion.setText("");
        jtextarea_Descripcion.setEditable(false);
        jbutton_Buscar.addActionListener(SS4_PantallaMenu);
        jbutton_Inscribirse.addActionListener(SS4_PantallaMenu);
        jbutton_Salir.addActionListener(SS4_PantallaMenu);

        setLayout(new BorderLayout());
        panelCentral = new JPanel();
        panelCentral.setLayout(null);
        panelCentral.add(jlabel_TipoEvento);
        panelCentral.add(jcomboBox_TipoEvento);
        panelCentral.add(jlabel_FechaInicial);
        panelCentral.add(jtextfield_FechaInicial);
        panelCentral.add(jlabel_FechaFinal);
        panelCentral.add(jtextfield_FechaFinal);
        panelCentral.add(jbutton_Buscar);
        panelCentral.add(jbutton_Inscribirse);
        panelCentral.add(jbutton_Salir);
        panelCentral.add(jlabel_Informacion);
        panelCentral.add(scrollPanelInformacion);
        panelCentral.add(jtextarea_Descripcion);
        add(panelCentral, BorderLayout.CENTER);
    }

    private JTable montarTablaInformacion() {
        tableInformacion = new JTable();
        tableInformacion.setBounds(new Rectangle(210, 60, 465, 140));
        tableInformacion.setName("tableInformacion");
        tableInformacion.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        tableInformacion.addMouseListener(new java.awt.event.MouseAdapter() {

            public void mouseClicked(java.awt.event.MouseEvent evt) {
                seleccionarEvento(evt);
            }
        });

        tableInformacion.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {null, null},
                    {null, null},
                    {null, null},
                    {null, null},
                    {null, null},
                    {null, null},
                    {null, null}
                },
                new String[]{
                    LanguageUtils.getMessage("InscripcionEvento.tableInformacion.Campo.Codigo"),
                    LanguageUtils.getMessage("InscripcionEvento.tableInformacion.Campo.Descripcion")}) {

            Class[] types = new Class[]{
                java.lang.Integer.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean[]{
                false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit[columnIndex];
            }
        });

        tableInformacion.getColumnModel().getColumn(0).setMaxWidth(0);
        tableInformacion.getColumnModel().getColumn(0).setMinWidth(0);
        tableInformacion.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(0);
        tableInformacion.getTableHeader().getColumnModel().getColumn(0).setMinWidth(0);

        tableInformacion.getColumnModel().getColumn(1).setResizable(false);
        tableInformacion.getColumnModel().getColumn(1).setHeaderValue(LanguageUtils.getMessage("InscripcionEvento.tableInformacion.Campo.Descripcion"));
        tableInformacion.getColumnModel().getColumn(1).setMinWidth(450);
        return tableInformacion;
    }

    /*
     * Accion que se ejecuta cuando se clica sobre la tabla
     */
    private void seleccionarEvento(java.awt.event.MouseEvent evt) {
        try {
            //Obtenemos el codigo del evento
            int v_FilaSeleccionada = tableInformacion.getSelectedRow();
            if (tableInformacion.getValueAt(v_FilaSeleccionada, 0) != null) {
                String v_IdEvento = tableInformacion.getValueAt(v_FilaSeleccionada, 0).toString();
                datosInscripcion = this.SS4_PantallaMenu.getRemotoConexion().getDatosInscripcion(v_IdEvento);

                //Cogemos los atributos del objetos para formatear el texto que visualizamos
                StringBuilder v_Texto = new StringBuilder();
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.FecEvento") + " " + datosInscripcion.getFecha() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.FecInscripcion") + " " + datosInscripcion.getFechainicioinscripcion() + " a " + datosInscripcion.getFechafininscripcion() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.Universidad") + " " + datosInscripcion.getNombreUniversidad() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.Centro") + " " + datosInscripcion.getNombreCentro() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.Localizacion") + " " + datosInscripcion.getLocalidad() + ", " + datosInscripcion.getDomicilio() + ", Telf." + datosInscripcion.getTelefono() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.Precio") + datosInscripcion.getPrecio() + "€ \n");

                //Indicamos prerrequisitos si los tiene
                List<SS2_Evento> prerrequisito = datosInscripcion.getPrerrequisito();
                if (prerrequisito.size() > 0) {
                    v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.Prerrequisito"));
                    for (int i = 0; i < prerrequisito.size(); i++) {
                        SS2_Evento evento = prerrequisito.get(i);
                        v_Texto.append("+ " + evento.getNombre() + "\n");
                    }
                }

                //Plazas totales y plazas ocupadas
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.TotalPlazas") + " " + datosInscripcion.getPlazas() + "\n");
                v_Texto.append(LanguageUtils.getMessage("InscripcionEvento.DatosEvento.PlazaOcupada") + " " + datosInscripcion.getInscritos() + "\n");
                datosInscripcion.setTextoFormateado(v_Texto.toString());
                jtextarea_Descripcion.setText(v_Texto.toString());
            }
        } catch (RemoteException ex) {
            ExceptionUtils.visualizarError(ExceptionUtils.ERR_Remote);
        } catch (Exception ex) {
            ExceptionUtils.visualizarError(LanguageUtils.getMessage("InscripcionEvento.ERR_DatosEvento"));
        }
    }

    /*
     * Metodo para rellenar el despegable de tipo de evento
     */
    private void setListTipoEventoToCombo(JComboBox combo) {
        try {
            List<SS1_TipoEvento> list = this.SS4_PantallaMenu.getRemotoConexion().getListaTipoEvento(this.acceso.getRol());
            if (list != null && list.size() > 0) {
                for (SS1_TipoEvento tipoEvento : list) {
                    combo.addItem(new KeyValue(Integer.toString(tipoEvento.getId()), tipoEvento.getTitulo()));
                }
            }
        } catch (RemoteException ex) {
            ExceptionUtils.visualizarError(ExceptionUtils.ERR_Remote);
        } catch (Exception ex) {
            ExceptionUtils.visualizarError(LanguageUtils.getMessage("InscripcionEvento.ERR_TipoEvento"));
        }
    }

    /**
     * Acción que se ejecutará al pulsar el botón
     * @param  Nombre del boton que se ha pulsado
     */
    public void componentePulsado(ActionEvent e) {
        if (e.getSource() == jbutton_Buscar) {
            buscarEvento();
        } else if (e.getSource() == jbutton_Inscribirse) {
            inscribirseEvento();
        } else if (e.getSource() == jbutton_Salir) {
            SS4_PantallaMenu.setPanelCentral(new SS4_PanelInicial());
        }
    }

    /*
     * Metodo que realiza la accion de inscribirse a un evento
     */
    private void inscribirseEvento() {
        try {
            String validarCondicionesMessage = validarInscripcion();
            if ("".equals(validarCondicionesMessage)) {
                SS4_PantallaMenu.setPanelCentral(new SS4_PantallaDatosInscripcion(this.SS4_PantallaMenu, datosInscripcion));
            } else {
                ExceptionUtils.visualizarError(LanguageUtils.getMessage("InscripcionEvento.Errores.Titulo") + validarCondicionesMessage);
            }
        } catch (RemoteException ex) {
            ExceptionUtils.visualizarError(ExceptionUtils.ERR_Remote);
        } catch (Exception ex) {
            ExceptionUtils.visualizarError(LanguageUtils.getMessage("InscripcionEvento.ERR_InscripcionEvento"));
        }
    }

    /*
     * Metodo que comprueba que se han introducido los campos obligatorios y el formato
     */
    private String validarInscripcion() throws RemoteException, Exception {
        //Validar que tiene un evento seleccionado
        int v_FilaSeleccionada = tableInformacion.getSelectedRow();
        if (v_FilaSeleccionada == -1) {
            return LanguageUtils.getMessage("InscripcionEvento.Errores.NoEvento");
        }
        if (tableInformacion.getValueAt(v_FilaSeleccionada, 0) == null) {
            return LanguageUtils.getMessage("InscripcionEvento.Errores.NoEvento");
        }
        String v_IdEvento = tableInformacion.getValueAt(v_FilaSeleccionada, 0).toString();

        //Validar que hay plazas libres
        if (datosInscripcion.getInscritos() >= datosInscripcion.getPlazas()) {
            return LanguageUtils.getMessage("InscripcionEvento.Errores.NoPlaza");
        }

        //Validar que no se haya inscrito ya al evento
        if (this.SS4_PantallaMenu.getRemotoConexion().getEstarInscrito(v_IdEvento, this.acceso.getCod_usuario())) {
            return LanguageUtils.getMessage("InscripcionEvento.Errores.EstarInscrito");
        }

        //Validar que se inscrite dentro de las fechas de inscripcion
        Date v_FecActual = new Date();
        if ((v_FecActual.compareTo(datosInscripcion.getFechainicioinscripcion()) < 0) || (v_FecActual.compareTo(datosInscripcion.getFechafininscripcion()) > 0)) {
            return LanguageUtils.getMessage("InscripcionEvento.ERR_FechasIncripcion");
        }

        //Validar que cumple los prerrequisitos de a ver asistido a los evento que se indican, si existen
        List<SS2_Evento> v_Prerrequisito = datosInscripcion.getPrerrequisito();
        if (v_Prerrequisito.size() > 0) {
            if (!this.SS4_PantallaMenu.getRemotoConexion().getAsistidoEvento(v_Prerrequisito, this.acceso.getCod_usuario())) {
                return LanguageUtils.getMessage("InscripcionEvento.ERR_Prerrequisito");
            }
        }

        return "";
    }

    /*
     * Metodo que realiza la busqueda de evento segun los parametros indicados
     */
    private void buscarEvento() {
        String validarCamposObligatoriosMessage = validarCamposObligatorios(jtextfield_FechaInicial.getText(), jtextfield_FechaFinal.getText());
        if ("".equals(validarCamposObligatoriosMessage)) {
            try {
                //Obtenemos los parametros a enviar
                KeyValue kv1 = (KeyValue) jcomboBox_TipoEvento.getItemAt(jcomboBox_TipoEvento.getSelectedIndex());
                String v_TipoEvento = (String) kv1.getKey();

                String[] v_FecIni = jtextfield_FechaInicial.getText().split("/");
                String[] v_FecFin = jtextfield_FechaFinal.getText().split("/");
                Date FecIni = sdf.parse(v_FecIni[0] + "/" + v_FecIni[1] + "/" + v_FecIni[2]);
                Date FecFin = sdf.parse(v_FecFin[0] + "/" + v_FecFin[1] + "/" + v_FecFin[2]);
                List<SS2_Evento> list = this.SS4_PantallaMenu.getRemotoConexion().getListaEvento(v_TipoEvento, sdf.format(FecIni), sdf.format(FecFin), this.acceso.getRol());
                borrarElementosTabla();
                //Comprobamos que la consulta nos ha devuelto datos
                if (list.size() > 0) {
                    DefaultTableModel tm = (DefaultTableModel) tableInformacion.getModel();
                    for (int i = 0; i < list.size(); i++) {
                        SS2_Evento evento = list.get(i);
                        Object[] rowData = new Object[]{evento.getidEvento(), evento.getdescripcion()};
                        tm.insertRow(i, rowData);
                    }
                } else {
                    ExceptionUtils.visualizarInformacion(LanguageUtils.getMessage("InscripcionEvento.NoDatos"));
                }
            } catch (RemoteException ex) {
                ExceptionUtils.visualizarError(ExceptionUtils.ERR_Remote);
            } catch (Exception ex) {
                ExceptionUtils.visualizarError(LanguageUtils.getMessage("InscripcionEvento.ERR_Buscar"));
            }
        } else {
            ExceptionUtils.visualizarError(LanguageUtils.getMessage("Acceso.CamposObligatorios") + validarCamposObligatoriosMessage);
        }
    }

    private void borrarElementosTabla() {
        DefaultTableModel tm = (DefaultTableModel) tableInformacion.getModel();
        if (tm != null && tm.getDataVector() != null) {
            tm.getDataVector().removeAllElements();
            tableInformacion.updateUI();
        }
    }

    /*
     * Metodo que comprueba que se han introducido los campos obligatorios y el formato
     */
    private String validarCamposObligatorios(String p_FechaInicial, String p_FechaFinal) {

        StringBuilder campos = new StringBuilder();
        if (p_FechaInicial == null || "".equals(p_FechaInicial)) {
            campos.append(LanguageUtils.getMessage("InscripcionEvento.CampoObligatorio.FechaInicial"));
        } else {
            if (!validarFecha(p_FechaInicial)) {
                campos.append(LanguageUtils.getMessage("InscripcionEvento.CampoObligatorio.FechaInicialFormatoIncorrecto"));
            }
        }

        if (p_FechaFinal == null || "".equals(p_FechaFinal)) {
            campos.append(LanguageUtils.getMessage("InscripcionEvento.CampoObligatorio.FechaFinal"));
        } else {
            if (!validarFecha(p_FechaFinal)) {
                campos.append(LanguageUtils.getMessage("InscripcionEvento.CampoObligatorio.FechaFinalFormatoIncorrecto"));
            }
        }

        if (validarFecha(p_FechaInicial) && validarFecha(p_FechaFinal)) {
            String[] v_FecIni = p_FechaInicial.split("/");
            String[] v_FecFin = p_FechaFinal.split("/");
            Date FecIni = new Date(Integer.parseInt(v_FecIni[2]), Integer.parseInt(v_FecIni[1]), Integer.parseInt(v_FecIni[0]));
            Date FecFin = new Date(Integer.parseInt(v_FecFin[2]), Integer.parseInt(v_FecFin[1]), Integer.parseInt(v_FecFin[0]));
            if (FecIni.compareTo(FecFin) > 0) {
                campos.append(LanguageUtils.getMessage("InscripcionEvento.CampoObligatorio.FecIniMayorFecFin"));
            }
        }
        return campos.toString();
    }

    private boolean validarFecha(String fecha) {
        try {
            sdf.setLenient(false);
            sdf.parse(fecha);
        } catch (ParseException pe) {
            return false;
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}
